/*
   (C) 2005 - Michael Ocean - Boston University

  This work is a part of the larger snBench project.  Information
  can be found at: http://csr.bu.edu/snbench

  This program is free software; you can redistribute it and/or
  modify it under the terms of Version 2 of the GNU General Public 
  License.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.
  
  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package sxe;

import java.util.ArrayList;
import step.Graph;
import snbenchlib.Trace;
import snbenchlib.Log;

/**
 * The NodeJanitor is responsible for periodically 
 * initiating the removal of nodes that have been 
 * marked as garbage. 
 *  
 * @author Michael
 *
 */

public class NodeJanitor extends Thread {
	private static final Integer SLEEP_TIME = 9000; /* in "real life" this will be 1 minute. */
	
	private boolean bRun;		/* indicates if the monitor is supposed to continue running */
	private boolean bDone;		/* indicates the monitor has completed running */
	private Graph	gStepToClean;	/* the graph being administered by this thread */			
	private GraphEvaluatorThread evaluator; /* handle to the evaluator, so it can be alerted when a delete occurs */
 	
	synchronized public boolean isDone(){ return bDone; }
	synchronized public void setDone(boolean _bdone) { bDone = _bdone; }
	synchronized public boolean isRun(){ return bRun; }
	synchronized public void setRun(boolean _brun) { 
		bRun = _brun;
	}

	synchronized public void Shutdown(){
		setRun(false);
		Log.janitor.log("Interrupting NodeJanitor",
				Trace.DEBUG);
		notifyAll();
	}
	
	public NodeJanitor(Graph g, GraphEvaluatorThread eval) {
		super();
		bRun = false;
		setDone(false);
		gStepToClean = g;
		evaluator = eval;
	}

	synchronized public void run() {
		Log.janitor.log("Starting NodeJanitor", Trace.DEBUG);
		setRun(true);

		while(isRun()){
			Log.janitor.log("doing another sweep", Trace.MINIMAL);
			gStepToClean.getWriteLock();
			Log.janitor.log("write locked", Trace.VERBOSE);
			gStepToClean.getReadLock();
			Log.janitor.log("read locked -- about to clean", Trace.VERBOSE);
			ArrayList<String> prunedNodes = gStepToClean.cleanup();
			gStepToClean.releaseWriteLock();
			Log.janitor.log("cleaning done.  write UNlocked.  About to update evaluator.", Trace.VERBOSE);
			evaluator.updateSchedueForNodeDeletion(prunedNodes);
			gStepToClean.releaseReadLock();
			Log.janitor.log("evaluator update done.  read UNlocked", Trace.VERBOSE);
			try {
				Log.janitor.log("about to sleep.", Trace.VERBOSE);
				Thread.currentThread().wait(SLEEP_TIME);
			} catch (InterruptedException e) {
				Log.janitor.log("sleep interrupted", Trace.MINIMAL);
				Log.janitor.printStackTrace(e,Trace.MINIMAL);
			}
		}		
		Log.janitor.log("NodeJanitor shut down",Trace.MINIMAL);
		setDone(true);
	}

}
